package com.botarena.server.servlets.http;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.logging.Logger;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.botarena.server.helper.Upload;
import com.botarena.server.services.AccountService;
import com.google.appengine.api.datastore.Blob;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.images.Image;
import com.google.appengine.api.images.ImagesService;
import com.google.appengine.api.images.ImagesServiceFactory;
import com.google.appengine.api.images.Transform;
import com.google.appengine.api.users.User;

public class UpdateAccountServlet extends HttpServlet {

	private static final long serialVersionUID = 2947991631037162748L;
	
	private static final Logger log = Logger.getLogger(UpdateAccountServlet.class.getName());
	
	private static final int MAX_AVATAR_SIZE = 200;

	private final AccountService accountService;

	public UpdateAccountServlet() {
		accountService = new AccountService();
	}

	@Override
	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		
		try {
			Upload upload = new Upload(request);
			
			String name = upload.getField("name");
			String deleteAvatarValue = upload.getField("deleteAvatar");
			boolean deleteAvatar = (deleteAvatarValue != null && deleteAvatarValue.equals("on"));
			
			ByteArrayOutputStream avatar = upload.getFile("avatarFile");
			
			Blob avatarBlob = null;
			if (avatar.size() > 0) {
				avatarBlob = prepareAvatar(avatar.toByteArray());
			}
			
			if (accountService.isLoggedIn()) {
				String accKey = upload.getField("accountKey");
				if (accKey != null && accKey.trim().length() > 0) {
					log.info("Updating account");
					Key key = KeyFactory.stringToKey(accKey);
					accountService.updateAccount(key, name, avatarBlob, deleteAvatar);
				} else {
					log.info("Creating new account");
					User gUser = accountService.getGoogleUser();
					accountService.createAccount(gUser, name, avatarBlob);
				}
			} else {
				String error = "You must be logged in to the Google Account service";
				response.getOutputStream().write(error.getBytes());
			}
			
		} catch (Exception e) {
			String error = "Cannot update account: " + e.getMessage();
			response.getOutputStream().write(error.getBytes());
			throw new ServletException(e);
		} finally {
			response.getOutputStream().close();
		}
	}
	
	private Blob prepareAvatar(byte[] data) {
		ImagesService imagesService = ImagesServiceFactory.getImagesService();
		
		Image image = ImagesServiceFactory.makeImage(data);
		
		Transform resize = null;
		
		double ratio = (double)image.getWidth() / (double)image.getHeight();
		if (image.getWidth() > image.getHeight()) {
			int width = Math.min(MAX_AVATAR_SIZE, image.getWidth());
			int height = (int)Math.round((double)width / ratio);
			resize = ImagesServiceFactory.makeResize(width, height);
		} else {
			int height = Math.min(MAX_AVATAR_SIZE, image.getHeight());
			int width = (int)Math.round((double)height * ratio);
			resize = ImagesServiceFactory.makeResize(width, height);			
		}
		
		Image newImage = imagesService.applyTransform(resize, image, ImagesService.OutputEncoding.JPEG);
		
		return new Blob(newImage.getImageData());
	}
	
}